import { isAddress } from '@ethersproject/address';

import Transaction from '../api/transaction/transaction';
import { EMAIL_REGEX } from '../constants/regex';
import { isOwnWallet } from './validate';

export interface CSVError {
    row: number;
    errors: Array<string>;
}

export const checkWalletAddress = (walletAddress: string, token: string): string => {
    if (!walletAddress) {
        return 'wallet address is empty';
    }

    if (token == 'SLP') {
        if (!walletAddress.startsWith('ronin:')) {
            return 'invalid Ronin address';
        }

        if (!isAddress(walletAddress.replace('ronin:', '0x'))) {
            return 'invalid wallet address';
        }
    } else {
        if (!isAddress(walletAddress)) {
            return 'invalid wallet address';
        }
    }

    return null;
};

export const checkForErrors = async (
    transaction: Transaction,
    minimumAmount: number,
    token: string
): Promise<CSVError> => {
    const rowErrors = new Array<string>();

    const amountError = checkAmount(transaction.amount, minimumAmount, token);

    if (amountError != null) {
        rowErrors.push(amountError);
    }

    const emailError = checkEmail(transaction.email);

    if (emailError != null) {
        rowErrors.push(emailError);
    }

    const walletAddressError = checkWalletAddress(transaction.walletAddress, token);

    if (walletAddressError != null) {
        rowErrors.push(walletAddressError);
    }

    const ownWalletError = await checkOwnWallet(transaction.walletAddress);

    if (ownWalletError != null) {
        rowErrors.push(ownWalletError);
    }

    // const hasDuplicateError = hasDuplicate(transaction.walletAddress, transactions);

    // if(hasDuplicateError != null) {
    //     rowErrors.push(hasDuplicateError)
    // }

    if (rowErrors.length > 0) {
        return {
            row: transaction.csvLine,
            errors: rowErrors,
        };
    }

    return null;
};

export const checkAmount = (amount: number, minimumAmount: number, token: string): string => {
    if (isNaN(amount) || amount <= 0) {
        return 'invalid amount';
    }

    if (amount < minimumAmount && token == 'SLP') {
        return 'amount should be at least ' + minimumAmount + ' ' + token;
    }

    return null;
};

export const checkEmail = (email: string): string => {
    if (!email) {
        return null;
    }

    if (!email.match(EMAIL_REGEX)) {
        return 'invalid email';
    }

    return null;
};

export const checkOwnWallet = async (walletAddress: string): Promise<string> => {
    if (await isOwnWallet(walletAddress)) {
        return 'you are sending to your own wallet';
    }

    return null;
};

export const hasDuplicate = (walletAddress: string, transactions: Array<Transaction>): string => {
    let count = 0;

    for (let i = 0; i < transactions.length; i++) {
        if (transactions[i].walletAddress == walletAddress) {
            count++;
        }
    }

    if (count > 1) {
        return 'has ' + (count - 1) + ' duplicate wallets';
    }

    return null;
};
